Kotlin伴生对象(Companion Object)

您所在的位置:网站首页 kotlin 安卓44 Kotlin伴生对象(Companion Object)

Kotlin伴生对象(Companion Object)

2023-09-23 17:13| 来源: 网络整理| 查看: 265

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第16天,点击查看活动详情

前言

Kotlin相对于Java还是有不少新特性的,本文就来介绍一下 伴生对象(companion object)的知识点。

本文大纲

Kotlin伴生对象Companion Object.png

0. 伴生对象(companion object)的诞生

伴生对象(companion object)的出现是为了解决 Java 静态方法(static)的反面向对象(Anti-OOP)的问题。我们知道 Java中,static 方法是无法声明为接口,无法被重写的。用学术性话语来说,static 方法没有面向对象的 消息传递 和 延迟绑定 特性[参考]。而为了满足Kotlin 一切皆对象的特性,以及提升与 Java 的兼容性,提出了伴生对象来代替 static 方法。

companion object 是一个对象,在类初始化时被实例化。 伴生对象不是类的 static 方法,而是类的实例化对象,所以在其内部可以声明接口,方法也可以被重写,具备面向对象的所有特点。

1. companion 的特性

声明伴生对象的语法:

companion object ObjectName : [0~N个父类型] { //伴生对象类体 } // ObjectName 可省略

特点:

伴生对象相当于类的对象,可直接通过类名访问伴生对象的成员; 每个类最多定义一个伴生对象; kotlin没有 static 关键字,伴生对象是为弥补kotlin没有 static 修饰的静态成员的不足; @JvmStatic 注解只能用在伴生对象里,修饰伴生对象内的属性和函数。 2. companion 的实现

在 Kotlin 中,调用 Java 的 static 方法和调用 Kotlin 的 companion object 方法是一样的:

JavaClass.staticFun() // 调用 Java 中静态方法 KotlinClass.companionFun() // 调用 Kotlin 中伴生对象的方法

而在 Java 中,调用 static 方法和 Kotlin 中伴生 companion object 方法,有点不同:

JavaClass.staticFun(); // Java 中调用 static 方法 KotlinClass.Companion.companionFun(); // 在Java中,调用伴生companion

从 Java 的调用可以发现,companion object 的 JVM 字节码,是一个声明了一个叫 Companion 的 static 变量。

而在 Kotlin 中调用一致,其实是编译器的特殊处理结果。

来反编译一下 KotlinClass,可以看到:

// KotlinClass.class public final class KotlinClass {   public static final Companion companion = new Companion(null); }

伴生对象 反编译后有如下代码:

// KotlinClass$Companion.class public final class KotlinClass$Companion {   private DownloadExecutor$Companion() {   }   public /* synthetic */ DownloadExecutor$Companion(DefaultConstructorMarker $constructor_marker) {       this();   }   public final void companionFun() {   } }

可以看到,Companion 是一个叫 KotlinClass$Companion 的类的实例,带 $ 符号表示这个类是 KotlinClass 的内部类,名字叫 Companion,所以在KotlinClass中直接new Companion(null)即可。

从上面的反编译代码看,实例化 Companion 使用的是一个带 DefaultConstructorMarker 入参的构造器。

出现的场景是,若 Kotlin 编译器生成特殊构造器,就会带这个参数。上面这段代码里 Kotlin 希望能实例化 Companion 类,但又不想声明一个 public 的构造器,就声明了一个特殊的构造器。DefaultConstructorMarker 值永远为 null。

DefaultConstructorMarker 的另一个场景是:带默认参数的构造器。

在掘金(JUEJIN)  一起分享知识,Keep Learning!



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3